﻿//
//
/////////////////////////////////////////////////////////////////////////////

using System;
using FreeSpaceLibrary.XnaContentObjects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
//using FreeSpace.Core;
//using FreeSpace.Logic;

/////////////////////////////////////////////////////////////////////////////
namespace FreeSpaceLibrary.Objects
{
    /////////////////////////////////////////////////////////////////////////
    public abstract class SpaceObject
    {
        protected int _id;
        protected ObjectData _data;
        //protected Vector2 _position;
        protected Rectangle _rectangle;
        protected float _radius;
        //protected float _velocity;
        protected Texture2D _objectTexture;
        protected SpriteBatch _sprite;
        protected Object _locker = new Object();
        private bool _isObjectInTheScreen = true;

        public delegate void ObjectOutoffScreen(SpaceObject sender, EventArgs eventArgs);
        public event ObjectOutoffScreen OnObjectOutoffScreen;

        /////////////////////////////////////////////////////////////////////
        protected SpaceObject(Vector2 position, float scaleFactor, Texture2D objectTexture, SpriteBatch sprite)
        {
            _data = new ObjectData {Position = position};

            _sprite = sprite;
            _objectTexture = objectTexture;

            if (scaleFactor > 0)
            {
                _rectangle = new Rectangle(Convert.ToInt32(_data.Position.X), Convert.ToInt32(_data.Position.Y * scaleFactor), Convert.ToInt32(_objectTexture.Width * scaleFactor), Convert.ToInt32(_objectTexture.Height * scaleFactor));
                _radius = (_objectTexture.Width + _objectTexture.Height) / 4f;
            }
            else
            {
                throw new Exception("The \"scaleFactor\" parameter should be greater then 0.");
            }
        }

        /////////////////////////////////////////////////////////////////////
        protected SpaceObject(float scaleFactor, Texture2D objectTexture, SpriteBatch sprite)
        {
            _data = new ObjectData { Position = Vector2.Zero};

            _sprite = sprite;
            _objectTexture = objectTexture;

            if (scaleFactor > 0)
            {
                _rectangle = new Rectangle(Convert.ToInt32(_data.Position.X), Convert.ToInt32(_data.Position.Y * scaleFactor), Convert.ToInt32(_objectTexture.Width * scaleFactor), Convert.ToInt32(_objectTexture.Height * scaleFactor));
                _radius = (_objectTexture.Width + _objectTexture.Height) / 4f;
            }
            else
            {
                throw new Exception("The \"scaleFactor\" parameter should be greater then 0.");
            }
        }

        ///////////////////////////////////////////////////////////////////
        protected SpaceObject(Texture2D objectTexture, SpriteBatch sprite)
        {
            _data = new ObjectData { Position = Vector2.Zero };
            
            _sprite = sprite;
            _objectTexture = objectTexture;

            const int scaleFactor = 1;
            _rectangle = new Rectangle(Convert.ToInt32(_data.Position.X), Convert.ToInt32(_data.Position.Y * scaleFactor), Convert.ToInt32(_objectTexture.Width * scaleFactor), Convert.ToInt32(_objectTexture.Height * scaleFactor));
            _radius = (_objectTexture.Width + _objectTexture.Height) / 4f;
        }

        /////////////////////////////////////////////////////////////////////
        protected SpaceObject(ObjectData data, float scaleFactor, SpriteBatch sprite)
        {
            if (data != null)
            {
                _id = data.Id;
                _data = data;
                _sprite = sprite;
                _objectTexture = ContentLoader.ContentTextures[(TextureEnum)data.Texture];

                if (scaleFactor > 0)
                {
                    _rectangle = new Rectangle(Convert.ToInt32(_data.Position.X), Convert.ToInt32(_data.Position.Y * scaleFactor), Convert.ToInt32(_objectTexture.Width * scaleFactor), Convert.ToInt32(_objectTexture.Height * scaleFactor));
                    _radius = (_objectTexture.Width + _objectTexture.Height) / 4f;
                }
                else
                {
                    throw new Exception("The \"scaleFactor\" parameter should be greater then 0.");
                }                
            }
            else
            {
                throw new Exception("The \"data\" parameter should be not null");
            }
        }

        /////////////////////////////////////////////////////////////////////
        protected SpaceObject(ObjectData data, SpriteBatch sprite)
        {
            if(data != null)
            {
                _id = data.Id;
                _data = data; 
                _sprite = sprite;
                _objectTexture = ContentLoader.ContentTextures[(TextureEnum)data.Texture];

                const int scaleFactor = 1;
                _rectangle = new Rectangle(Convert.ToInt32(_data.Position.X), Convert.ToInt32(_data.Position.Y * scaleFactor), Convert.ToInt32(_objectTexture.Width * scaleFactor), Convert.ToInt32(_objectTexture.Height * scaleFactor));
                _radius = (_objectTexture.Width + _objectTexture.Height) / 4f;
            }
            else
            {
                throw new Exception("The \"data\" parameter should be not null");
            }
        }

        /////////////////////////////////////////////////////////////////////
        public Vector2 Position
        {
            get { return _data.Position; }
            set
            {
                //_position = value;
                _data.Position = value;
                _rectangle.X = Convert.ToInt32(value.X);
                _rectangle.Y = Convert.ToInt32(value.Y);
            }
        }

        /////////////////////////////////////////////////////////////////////
        public float Height
        {
            get { return _rectangle.Height; }
        }

        /////////////////////////////////////////////////////////////////////
        public float Width
        {
            get { return _rectangle.Width; }
        }

        /////////////////////////////////////////////////////////////////////
        public float Radius
        {
            get { return _radius; }
            protected set { _radius = value; }
        }

        /////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Speed. Pixels per second (1000 msec)
        /// </summary>
        public float Velocity
        {
            //get { return _velocity; }
            //set { _velocity = value; }
            get { return _data.Velocity; }
            set { _data.Velocity = value; }
        }

        /////////////////////////////////////////////////////////////////////
        public bool InScreen
        {
            get { return _isObjectInTheScreen; }
        }

        /////////////////////////////////////////////////////////////////////
        public virtual void Draw()
        {
            _sprite.Begin();
            _sprite.Draw(_objectTexture, _rectangle, Color.White);
            _sprite.End();
        }

        /////////////////////////////////////////////////////////////////////
        public void StepUp(double time)
        {
            float newValue = Position.Y - _data.Velocity * (float)time / 1000.0f;
            Position = new Vector2(Position.X, newValue);
        }

        /////////////////////////////////////////////////////////////////////
        public void StepDown(double time)
        {
            float newValue = Position.Y + _data.Velocity * (float)time / 1000.0f;
            if (Position.Y < Constants.ScreenHeight)
            {
                Position = new Vector2(Position.X, newValue);
            }
            //else if(OnObjectOutoffScreen != null)
            //{
            //    OnObjectOutoffScreen(this, new EventArgs());
            //    _isObjectInTheScreen = false;
            //}
        }

        /////////////////////////////////////////////////////////////////////
        public void StepDown(double time, float speed)
        {
            float newValue = Position.Y + speed * (float)time / 1000.0f;
            if (Position.Y < Constants.ScreenHeight)
            {
                Position = new Vector2(Position.X, newValue);
            }
            //else if (OnObjectOutoffScreen != null)
            //{
            //    OnObjectOutoffScreen(this, new EventArgs());
            //    _isObjectInTheScreen = false;
            //}
        }

        /////////////////////////////////////////////////////////////////////
        public void StepLeft(double time)
        {
            float newValue = Position.X - _data.Velocity * (float)time / 1000.0f;
            if (newValue > 0)
            {
                Position = new Vector2(newValue, Position.Y);
            }
            //else if (OnObjectOutoffScreen != null)
            //{
            //    OnObjectOutoffScreen(this, new EventArgs());
            //    _isObjectInTheScreen = false;
            //}
        }

        /////////////////////////////////////////////////////////////////////
        public void StepRight(double time)
        {
            float newValue = Position.X + _data.Velocity * (float)time / 1000.0f;
            if (newValue < Constants.ScreenWidth)
            {
                Position = new Vector2(newValue, Position.Y);
                //_isObjectInTheScreen = true;
            }
            //else if (OnObjectOutoffScreen != null)
            //{
            //    OnObjectOutoffScreen(this, new EventArgs());
            //    _isObjectInTheScreen = false;
            //}
        }

        /////////////////////////////////////////////////////////////////////
        public virtual void Update(GameTime gameTime, KeyboardState keyboardState)
        {
            if (Position.Y > Constants.ScreenHeight || Position.Y < -_rectangle.Height || Position.X > _rectangle.Width + Constants.ScreenWidth || Position.X < -_rectangle.Width)
            {
                if (OnObjectOutoffScreen != null)
                {
                    OnObjectOutoffScreen(this, new EventArgs());
                    _isObjectInTheScreen = false;
                }
                else
                {
                    _isObjectInTheScreen = true;
                }
            }
        }
    }
    /////////////////////////////////////////////////////////////////////////////
}//FreeSpace.Logic